package org.ns.learn.rpc;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.ns.learn.rpc.codec.ParameterType;
import org.ns.learn.rpc.codec.RpcRequest;
import org.ns.learn.rpc.codec.RpcResponse;
import org.springframework.aop.support.AopUtils;
import org.springframework.context.ApplicationContext;

import java.lang.reflect.Method;
import java.util.Collection;

public class RpcServerHandler extends ChannelInboundHandlerAdapter {
    ApplicationContext applicationContext;

    public RpcServerHandler(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("有一连接进入！");
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("有一RPC请求进入！");
        RpcRequest request = (RpcRequest) msg;
        RpcResponse response = new RpcResponse(request.getRequestId());
        String beanName = request.getBeanName();
        String methodName = request.getMethodName();

        try {
            if (!applicationContext.containsBean(beanName)) {
                response.setError("未找到beanName: " + beanName);
                return;
            }
            Object bean = applicationContext.getBean(beanName);
            Method method;
            try {
                Class<?> targetClass = AopUtils.getTargetClass(bean);
                Class<?>[] classes = request.toTypes();
                method = targetClass.getDeclaredMethod(methodName, classes);
            } catch (NoSuchMethodException e) {
                response.setError("未找到方法: " + methodName);
                return;
            }
            Object[] parameters = request.getParameters();
            try {
                Object result = method.invoke(bean, parameters);
                Class<?> returnType = method.getReturnType();
                Class<?> componentType = Object.class;
                if (Collection.class.isAssignableFrom(returnType)) {
                    if (result != null && ((Collection<?>) result).size() > 0) {
                        Object first = ((Collection<?>) result).iterator().next();
                        if (first != null) {
                            componentType = first.getClass();
                        }
                    }
                }


                response.setResult(result);
                response.setParameterType(new ParameterType(returnType, componentType));
                System.out.println("结果:" + result);
                ctx.writeAndFlush(response);
            } catch (Throwable e) {
                e.printStackTrace();
                response.setError("远程方法执行异常！");
            }
        } finally {
            ctx.writeAndFlush(response);
        }
    }
}
